﻿Ext.gesture.Gesture = Ext.extend(Object, {
    listenForStart: true,
    listenForEnd: true,
    listenForMove: true,

    disableLocking: false,

    touches: 1,

    constructor: function (config) {
        config = config || {};
        Ext.apply(this, config);

        this.target = Ext.getDom(this.target);
        this.listeners = {};


        if (!this.target) {
            throw new Error('Trying to bind a ' + this.type + ' event to element that does\'nt exist: ' + this.target);
        }


        this.id = this.target.id + '-' + this.type;//生成id

        Ext.gesture.Gesture.superclass.constructor.call(this);

        Ext.gesture.Manager.register(this);//向管理类注册该实例
    },

    //给gesture对象添加事件侦听函数,listener是在Ext.EventManager那里生成的新函数
    addListener: function (name, listener) {
        this.listeners[name] = this.listeners[name] || [];
        this.listeners[name].push(listener);//将listener放入this.listeners中指定的数组里
    },

    removeListener: function (name, listener) {
        var listeners = this.listeners[name];

        if (listeners) {
            listeners.remove(listener);

            if (listeners.length == 0) {
                delete this.listeners[name];
            }

            for (name in this.listeners) {
                if (this.listeners.hasOwnProperty(name)) {
                    return;
                }
            }

            this.listeners = {};
        }
    },

    //触发事件type：事件名，e: 事件对象，args：参数
    //被onTouchStart、onTouchMove、onTouchEnd三个函数触发,而这三个函数又被Ext.getsture.Manager的同名函数触发
    //Ext.getsture.Manager的同名函数则直接被浏览器的原生事件触发
    fire: function (type, e, args) {
        var listeners = this.listeners && this.listeners[type],//获取事件的所有侦听函数
            ln = listeners && listeners.length,
            i;

        if (!this.disableLocking && this.isLocked(type)) {//如果事件被锁，则直接返回false
            return false;
        }

        if (ln) {
            args = Ext.apply(args || {}, {
                time: e.timeStamp,
                type: type,
                gesture: this,
                target: (e.target.nodeType == 3) ? e.target.parentNode : e.target
            });

            for (i = 0; i < ln; i++) {//循环执行元素级侦听函数
                listeners[i](e, args);
            }
        }

        return true;
    },

    stop: function () {
        Ext.gesture.Manager.stopGesture(this);
    },

    lock: function () {
        if (!this.disableLocking) {
            var args = arguments,
                ln = args.length,
                i;

            for (i = 0; i < ln; i++) {
                Ext.gesture.Manager.locks[args[i]] = this.id;
            }
        }
    },

    unlock: function () {
        if (!this.disableLocking) {
            var args = arguments,
                ln = args.length,
                i;

            for (i = 0; i < ln; i++) {
                if (Ext.gesture.Manager.locks[args[i]] == this.id) {
                    delete Ext.gesture.Manager.locks[args[i]];
                }
            }
        }
    },

    isLocked: function (type) {
        var lock = Ext.gesture.Manager.locks[type];
        return !!(lock && lock !== this.id);
    },

    getLockingGesture: function (type) {
        var lock = Ext.gesture.Manager.locks[type];
        if (lock) {
            return Ext.gesture.Manager.get(lock) || null;
        }
        return null;
    },

    onTouchStart: Ext.emptyFn,
    onTouchMove: Ext.emptyFn,
    onTouchEnd: Ext.emptyFn,

    destroy: function () {
        this.stop();
        this.listeners = null;
        Ext.gesture.Manager.unregister(this);
    }
});